/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.fyx.linker.web.category;

import java.util.LinkedList;
import java.util.List;
import org.fyx.linker.entity.LinkerCategory;
import org.fyx.linker.entity.LinkerLink;
import org.primefaces.component.menuitem.MenuItem;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;

/**
 * Vlastni implementace treeNode, ktera uchovava navic seznam odkazu
 * a kategorii urciteho uzlu stromu.
 * @author xljan
 */
public class CategoryTreeNode extends DefaultTreeNode {

    /**
     * Odkazy v urcitem uzlu stromu.
     */
    private List<MenuItem> menuItems = new LinkedList<MenuItem>();
    /**
     * Kategorie vztahujici se k urcitemu uzlu stromu.
     */
    private LinkerCategory category;

    public CategoryTreeNode() {
        super();
    }

    public CategoryTreeNode(Object data, TreeNode parent) {
        super(data, parent);
    }

    public CategoryTreeNode(LinkerCategory category, TreeNode parent) {
        super(category, parent);
        this.category = category;
    }

    public CategoryTreeNode(String type, Object data, TreeNode parent) {
        super(type, data, parent);
    }

    public List<MenuItem> getMenuItems() {
        return menuItems;
    }

    public void setMenuItems(List<MenuItem> menuItems) {
        this.menuItems = menuItems;
    }

    public LinkerCategory getCategory() {
        return category;
    }

    public void setCategory(LinkerCategory category) {
        this.category = category;
    }

    /**
     * Kaskadove synchronizuje uzivatelsky model (TreeNode, MenuItems) s 
     * databazovym modelem (LinkerCategory, LinkerLink).
     */
    
    public void synchronizeCascade() {
        synchronizeLinks();
        category.getLinkerCategoryCollection().clear();
        for (TreeNode child : getChildren()) {
            ((CategoryTreeNode) child).getCategory().setParent(category);
            category.getLinkerCategoryCollection().
                    add(((CategoryTreeNode) child).category);
            ((CategoryTreeNode) child).synchronizeCascade();
        }
    }

    /**
     * Synchronizuje polozky z menuItems do seznamu linku.
     * Vymaze ty linky ktere nejsou v seznamu menu items.
     * Zmeni hodnoty linku ktere maji stejne ID.
     * Pro ostatni menuItem vytvori nove linky.
     */
    public void synchronizeLinks() {
        int priority = 1;
        category.getLinkerLinkCollection().clear();
        for (MenuItem menuItem : menuItems) {
            LinkerLink link = new LinkerLink(menuItem.getId());
            link.setIdCategory(category);
            link.setPriority(priority++);
            category.getLinkerLinkCollection().add(link);
        }
    }

    /**
     * Kaskadove odebere vsechny uzly stromu pocinaje sam sebou.
     * 
     * @return seznam vsech obsazenych MenuItem
     */
    public List<MenuItem> removeCascade() {
        getParent().getChildren().remove(this);
        return getCascadeChildren();
    }
    
    /**
     * Vrati seznam vsech potomku typu {@link MenuItem}.
     * 
     * @return seznam vsech potomku MenuItem
     */
    public List<MenuItem> getCascadeChildren() {
        List<MenuItem> children = new LinkedList<MenuItem>(getMenuItems());
        for (TreeNode child : getChildren()) {
            children.addAll(((CategoryTreeNode) child).getCascadeChildren());
        }
        return children;
    }

    @Override
    public String toString() {
        return category.getName();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }

        CategoryTreeNode other = (CategoryTreeNode) obj;
        if (category == null) {
            if (other.category != null) {
                return false;
            }
        } else if (!category.equals(other.category) 
                || !category.getName().equals(other.category.getName())) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 79 * hash + (this.category != null ? this.category.hashCode() : 0);
        return hash;
    }
}
